package jnpf.onlinedev.controller;


import cn.hutool.core.util.ObjectUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.entity.VisualdevEntity;
import jnpf.base.model.VisualDevJsonModel;
import jnpf.base.model.VisualWebTypeEnum;
import jnpf.base.service.DbLinkService;
import jnpf.base.service.VisualdevService;
import jnpf.base.util.VisualUtils;
import jnpf.base.vo.DownloadVO;
import jnpf.base.vo.PaginationVO;
import jnpf.config.ConfigValueUtil;
import jnpf.constant.MsgCode;
import jnpf.database.model.entity.DbLinkEntity;
import jnpf.engine.entity.FlowEngineEntity;
import jnpf.engine.entity.FlowTaskEntity;
import jnpf.engine.model.DataModel;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.service.FlowEngineService;
import jnpf.engine.service.FlowTaskService;
import jnpf.engine.util.FlowDataUtil;
import jnpf.engine.util.OnlineDevFormUtils;
import jnpf.exception.DataException;
import jnpf.exception.WorkFlowException;
import jnpf.model.visiual.ColumnDataModel;
import jnpf.model.visiual.FormDataModel;
import jnpf.model.visiual.OnlineDevData;
import jnpf.model.visiual.TableModel;
import jnpf.model.visiual.fields.FieLdsModel;
import jnpf.onlinedev.entity.VisualdevModelDataEntity;
import jnpf.onlinedev.model.*;
import jnpf.onlinedev.service.VisualDevInfoService;
import jnpf.onlinedev.service.VisualDevListService;
import jnpf.onlinedev.service.VisualdevModelDataService;
import jnpf.onlinedev.util.AutoFeildsUtil;
import jnpf.onlinedev.util.OnlineDevDbUtil;
import jnpf.onlinedev.util.onlineDevUtil.OnlineDevListUtils;
import jnpf.onlinedev.util.onlineDevUtil.OnlinePublicUtils;
import jnpf.onlinedev.util.onlineDevUtil.OnlineSwapDataUtils;
import jnpf.util.*;
import jnpf.util.enums.ExportModelTypeEnum;
import jnpf.util.enums.ModuleTypeEnum;
import jnpf.util.file.FileExport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 0代码无表开发
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2019年9月27日 上午9:18
 */
@Slf4j
@Api(tags = "0代码无表开发", value = "OnlineDev")
@RestController
@RequestMapping("/api/visualdev/OnlineDev")
public class VisualdevModelDataController {


    @Autowired
    private VisualdevModelDataService visualdevModelDataService;
    @Autowired
    private VisualdevService visualdevService;
    @Autowired
    private ConfigValueUtil configValueUtil;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private FileExport fileExport;
    @Autowired
    private FlowEngineService flowEngineService;
    @Autowired
    private FlowTaskService flowTaskService;
    @Autowired
    private VisualDevListService visualDevListService;
    @Autowired
    private DbLinkService dblinkService;
    @Autowired
    private FlowDataUtil flowDataUtil;
    @Autowired
    private VisualDevInfoService visualDevInfoService;
    @Autowired
    private OnlineSwapDataUtils onlineSwapDataUtils;

    public ConcurrentHashMap<String, Integer> concurrentHashMap = new ConcurrentHashMap();

    @ApiOperation("获取数据列表")
    @PostMapping("/{modelId}/List")
    public ActionResult list(@PathVariable("modelId") String modelId, @RequestBody PaginationModel paginationModel) {
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
        VisualDevJsonModel visualJsonModel = OnlinePublicUtils.getVisualJsonModel(visualdevEntity);

        //处理旧数据 第一次加载页面后 可删除该方法
        if (concurrentHashMap.get(modelId) == null) {
            try {
                OnlineDevDbUtil.dataSynchro(visualJsonModel);
                concurrentHashMap.put(modelId, 1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //判断请求客户端来源
        String header = ServletUtil.getHeader("jnpf-origin");

        if (!"pc".equals(header)) {
            visualJsonModel.setColumnData(visualJsonModel.getAppColumnData());
        }

        List<Map<String, Object>> realList;
        if (VisualWebTypeEnum.FORM.getType().equals(visualdevEntity.getWebType())) {
            realList = new ArrayList<>();
        } else {
            realList = visualDevListService.getDataList(visualJsonModel, paginationModel);
        }

        ColumnDataModel columnDataModel = visualJsonModel.getColumnData();
        //判断数据是否分组
        if (OnlineDevData.TYPE_THREE_COLUMNDATA.equals(columnDataModel.getType())) {
            realList = OnlineDevListUtils.groupData(realList, columnDataModel);
        }

        PaginationVO paginationVO = JsonUtil.getJsonToBean(paginationModel, PaginationVO.class);

        return ActionResult.page(realList, paginationVO);
    }

    @ApiOperation("获取列表表单配置JSON")
    @GetMapping("/{modelId}/Config")
    public ActionResult getData(@PathVariable("modelId") String modelId) {
        VisualdevEntity entity = visualdevService.getInfo(modelId);
        if (entity == null) {
            return ActionResult.fail("功能不存在");
        }
        if (entity.getState() == 0) {
            return ActionResult.fail("功能未启用");
        }
        DataInfoVO vo = JsonUtil.getJsonToBean(entity, DataInfoVO.class);
        if (ObjectUtil.isNotEmpty(entity.getWebType())) {
            if (entity.getWebType() != null && VisualWebTypeEnum.FLOW_FROM.getType().equals(entity.getWebType())) {
                try {
                    FlowEngineEntity engineEntity = flowEngineService.getInfo(entity.getFlowId());
                    if (Objects.nonNull(engineEntity)) {
                        vo.setFlowEnCode(engineEntity.getEnCode());
                        vo.setFlowId(entity.getFlowId());
                    }
                } catch (WorkFlowException e) {
                    e.printStackTrace();
                }
            }
        }
        return ActionResult.success(vo);
    }


    @ApiOperation("获取列表配置JSON")
    @GetMapping("/{modelId}/ColumnData")
    public ActionResult getColumnData(@PathVariable("modelId") String modelId) {
        VisualdevEntity entity = visualdevService.getInfo(modelId);
        FormDataInfoVO vo = JsonUtil.getJsonToBean(entity, FormDataInfoVO.class);
        return ActionResult.success(vo);
    }


    @ApiOperation("获取表单配置JSON")
    @GetMapping("/{modelId}/FormData")
    public ActionResult<ColumnDataInfoVO> getFormData(@PathVariable("modelId") String modelId) {
        VisualdevEntity entity = visualdevService.getInfo(modelId);
        ColumnDataInfoVO vo = JsonUtil.getJsonToBean(entity, ColumnDataInfoVO.class);
        return ActionResult.success(vo);
    }

    @ApiOperation("获取工作流模板JSON")
    @GetMapping("/{modelId}/FlowTemplate")
    public ActionResult getFlowTemplate(@PathVariable("modelId") String modelId) {
        VisualdevEntity entity = visualdevService.getInfo(modelId);
        FlowTemplateInfoVo vo = JsonUtil.getJsonToBean(entity, FlowTemplateInfoVo.class);
        return ActionResult.success(vo);
    }

    @ApiOperation("获取数据信息")
    @GetMapping("/{modelId}/{id}")
    public ActionResult info(@PathVariable("id") String id, @PathVariable("modelId") String modelId) throws DataException, ParseException, SQLException, IOException {
        id = XSSEscape.escape(id);
        modelId = XSSEscape.escape(modelId);
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
        //有表
        if (!StringUtil.isEmpty(visualdevEntity.getVisualTables()) && !OnlineDevData.TABLE_CONST.equals(visualdevEntity.getVisualTables())) {
            VisualdevModelDataInfoVO editDataInfo = visualDevInfoService.getEditDataInfo(id, visualdevEntity);
            return ActionResult.success(editDataInfo);
        }
        //无表
        VisualdevModelDataEntity entity = visualdevModelDataService.getInfo(id);
        Map<String, Object> formData = JsonUtil.stringToMap(visualdevEntity.getFormData());
        List<FieLdsModel> modelList = JsonUtil.getJsonToList(formData.get("fields").toString(), FieLdsModel.class);
        //去除模板多级控件
        modelList = VisualUtils.deleteMore(modelList);
        String data = AutoFeildsUtil.autoFeilds(modelList, entity.getData());
        entity.setData(data);
        VisualdevModelDataInfoVO vo = JsonUtilEx.getJsonToBeanEx(entity, VisualdevModelDataInfoVO.class);
        return ActionResult.success(vo);
    }

    @ApiOperation("获取数据信息(带转换数据)")
    @GetMapping("/{modelId}/{id}/DataChange")
    public ActionResult infoWithDataChange(@PathVariable("modelId") String modelId, @PathVariable("id") String id) throws DataException, ParseException, IOException, SQLException {
        modelId = XSSEscape.escape(modelId);
        id = XSSEscape.escape(id);
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);

        //有表
        if (!StringUtil.isEmpty(visualdevEntity.getVisualTables()) && !OnlineDevData.TABLE_CONST.equals(visualdevEntity.getVisualTables())) {
            VisualdevModelDataInfoVO vo = visualDevInfoService.getDetailsDataInfo(id, visualdevEntity);
            return ActionResult.success(vo);
        }
        //无表
        VisualdevModelDataInfoVO vo = visualdevModelDataService.infoDataChange(id, visualdevEntity);
        return ActionResult.success(vo);
    }


    @ApiOperation("添加数据")
    @PostMapping("/{modelId}")
    public ActionResult create(@PathVariable("modelId") String modelId, @RequestBody VisualdevModelDataCrForm visualdevModelDataCrForm) throws WorkFlowException {
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
        Map<String, Object> map = JsonUtil.stringToMap(visualdevModelDataCrForm.getData());
        FormDataModel formData = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        DbLinkEntity linkEntity = StringUtil.isNotEmpty(visualdevEntity.getDbLinkId()) ? dblinkService.getInfo(visualdevEntity.getDbLinkId()) : null;
        //是否开启并发锁
        Boolean concurrency = false;
        Integer primaryKeyPolicy = formData.getPrimaryKeyPolicy();
        if (formData.getConcurrencyLock()) {
            //初始化version值
            map.put("f_version", 0);
            concurrency = true;
        }
        //单行唯一校验
        boolean b = OnlineDevFormUtils.checkForm(list, map, linkEntity, tableModels, primaryKeyPolicy, null);
        if (!b) {
            return ActionResult.fail("单行输入不能重复");
        }
        String mainId = RandomUtil.uuId();
        UserInfo userInfo = userProvider.get();
        DataModel dataModel = DataModel.builder().dataNewMap(map).fieLdsModelList(list).tableModelList(tableModels).mainId(mainId).link(linkEntity).userInfo(userInfo).concurrencyLock(concurrency).primaryKeyPolicy(primaryKeyPolicy).build();
        FlowModel flowModel = JsonUtil.getJsonToBean(visualdevModelDataCrForm, FlowModel.class);
        flowDataUtil.create(dataModel);
        ActionResult actionResult = visualdevModelDataService.visualCreate(visualdevEntity, map, visualdevModelDataCrForm, mainId, flowModel);
        return actionResult;
    }


    @ApiOperation("修改数据")
    @PutMapping("/{modelId}/{id}")
    public ActionResult update(@PathVariable("id") String id, @PathVariable("modelId") String modelId, @RequestBody VisualdevModelDataUpForm visualdevModelDataUpForm) throws DataException, SQLException, WorkFlowException {
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
        ColumnDataModel columnDataModel = JsonUtil.getJsonToBean(visualdevEntity.getColumnData(), ColumnDataModel.class);
        FormDataModel formData = JsonUtil.getJsonToBean(visualdevEntity.getFormData(), FormDataModel.class);
        List<FieLdsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieLdsModel.class);
        boolean inlineEdit = columnDataModel.getType() != null && columnDataModel.getType() == 4;
        if (inlineEdit) {
            list = JsonUtil.getJsonToList(columnDataModel.getColumnList(), FieLdsModel.class);
            list = list.stream().filter(f -> !f.getVModel().contains("tableField")).collect(Collectors.toList());
        }
        Map<String, Object> map = JsonUtil.stringToMap(visualdevModelDataUpForm.getData());
        List<TableModel> tableModels = JsonUtil.getJsonToList(visualdevEntity.getVisualTables(), TableModel.class);
        TableModel mainT = tableModels.stream().filter(t -> t.getTypeId().equals("1")).findFirst().orElse(null);
        DbLinkEntity linkEntity = StringUtil.isNotEmpty(visualdevEntity.getDbLinkId()) ? dblinkService.getInfo(visualdevEntity.getDbLinkId()) : null;
        //是否开启并发锁
        Boolean isConcurrencyLock = false;
        Integer primaryKeyPolicy = formData.getPrimaryKeyPolicy();
        if (formData.getConcurrencyLock()) {
            if (map.get("f_version") == null) {
                map.put("f_version", 0);
            } else {
                boolean version = VisualUtils.getVersion(mainT.getTable(), linkEntity, map, id, primaryKeyPolicy);
                if (!version) {
                    return ActionResult.fail("当前表单原数据已被调整，请重新进入该页面编辑并提交数据");
                } else {
                    Integer vs = Integer.valueOf(String.valueOf(map.get("f_version")));
                    map.put("f_version", vs + 1);
                }
            }
            isConcurrencyLock = true;
        }

        boolean b = OnlineDevFormUtils.checkForm(list, map, linkEntity, tableModels, primaryKeyPolicy, id);
        if (!b) {
            return ActionResult.fail("单行输入不能重复");
        }
        UserInfo userInfo = userProvider.get();
        DataModel dataModel = DataModel.builder().dataNewMap(map).fieLdsModelList(list).tableModelList(tableModels).mainId(id).link(linkEntity).userInfo(userInfo).concurrencyLock(isConcurrencyLock).primaryKeyPolicy(primaryKeyPolicy).build();
        FlowModel flowModel = JsonUtil.getJsonToBean(visualdevModelDataUpForm, FlowModel.class);
        ActionResult actionResult = visualdevModelDataService.visualUpdate(id, visualdevEntity, map, visualdevModelDataUpForm, flowModel);
        flowDataUtil.update(dataModel);
        return actionResult;
    }


    @ApiOperation("删除数据")
    @DeleteMapping("/{modelId}/{id}")
    public ActionResult delete(@PathVariable("id") String id, @PathVariable("modelId") String modelId) throws Exception {
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);

        VisualDevJsonModel visualJsonModel = OnlinePublicUtils.getVisualJsonModel(visualdevEntity);

        //判断请求客户端来源
        String header = ServletUtil.getHeader("jnpf-origin");

        if (!"pc".equals(header)) {
            visualJsonModel.setColumnData(visualJsonModel.getAppColumnData());
        }

        //删除流程任务
        if (ObjectUtil.isNotEmpty(visualdevEntity.getWebType())) {
            if (visualdevEntity.getWebType() != null && VisualWebTypeEnum.FLOW_FROM.getType().equals(visualdevEntity.getWebType())) {
                if (StringUtil.isNotEmpty(visualdevEntity.getFlowId())) {
                    FlowTaskEntity taskEntity = flowTaskService.getInfoSubmit(id, FlowTaskEntity::getId, FlowTaskEntity::getStatus);
                    if (taskEntity != null) {
                        flowTaskService.delete(taskEntity);
                    }
                } else {
                    return ActionResult.fail("未关联流程引擎");
                }
            }
        }
        if (!StringUtil.isEmpty(visualdevEntity.getVisualTables()) && !OnlineDevData.TABLE_CONST.equals(visualdevEntity.getVisualTables())) {
            boolean result = visualdevModelDataService.tableDelete(id, visualJsonModel);
            if (result) {
                return ActionResult.success(MsgCode.SU003.get());
            } else {
                return ActionResult.fail(MsgCode.FA003.get());
            }
        }
        VisualdevModelDataEntity entity = visualdevModelDataService.getInfo(id);
        if (entity != null) {
            visualdevModelDataService.delete(entity);
            return ActionResult.success(MsgCode.SU003.get());
        }
        return ActionResult.fail(MsgCode.FA003.get());
    }

    @ApiOperation("批量删除数据")
    @PostMapping("/batchDelete/{modelId}")
    public ActionResult beachDelete(@RequestBody BatchRemoveIdsVo idsVo, @PathVariable("modelId") String modelId) throws Exception {
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);

        VisualDevJsonModel visualJsonModel = OnlinePublicUtils.getVisualJsonModel(visualdevEntity);

        //判断请求客户端来源
        String header = ServletUtil.getHeader("jnpf-origin");

        if (!"pc".equals(header)) {
            visualJsonModel.setColumnData(visualJsonModel.getAppColumnData());
        }

        List<String> idsList = new ArrayList<>();
        List<String> idsVoList = Arrays.asList(idsVo.getIds());
        if (visualdevEntity.getWebType() != null && visualdevEntity.getWebType().equals(VisualWebTypeEnum.FLOW_FROM.getType())) {
            for (String id : idsVoList) {
                FlowTaskEntity taskEntity = flowTaskService.getInfoSubmit(id, FlowTaskEntity::getId, FlowTaskEntity::getStatus);
                if (taskEntity != null) {
                    if (taskEntity.getStatus().equals(0) || taskEntity.getStatus().equals(4)) {
                        idsList.add(id);
                        flowTaskService.delete(taskEntity);
                    }
                } else {
                    idsList.add(id);
                }
            }
        } else {
            idsList = idsVoList;
        }
        if (idsList.size() == 0) {
            return ActionResult.fail("该流程已发起，无法删除");
        }
        if (!StringUtil.isEmpty(visualdevEntity.getVisualTables()) && !OnlineDevData.TABLE_CONST.equals(visualdevEntity.getVisualTables())) {
            ActionResult result = visualdevModelDataService.tableDeleteMore(idsList, visualJsonModel);
            return result;
        }
        if (visualdevModelDataService.removeByIds(idsList)) {
            return ActionResult.success(MsgCode.SU003.get());
        } else if (visualdevEntity.getWebType() != null && visualdevEntity.getWebType().equals(VisualWebTypeEnum.FLOW_FROM.getType()) && idsList.size() > 0) {
            //分组页面
            return ActionResult.fail("该流程已发起，无法删除");
        }
        return ActionResult.fail(MsgCode.FA003.get());
    }


    @ApiOperation("导入")
    @PostMapping("/Model/{modelId}/Actions/Import")
    public ActionResult imports(@PathVariable("modelId") String modelId) {
        VisualdevModelDataEntity entity = visualdevModelDataService.getInfo(modelId);
        List<MultipartFile> list = UpUtil.getFileAll();
        MultipartFile file = list.get(0);
        if (file.getOriginalFilename().contains(".xlsx")) {
            String filePath = configValueUtil.getTemporaryFilePath();
            String fileName = RandomUtil.uuId() + "." + UpUtil.getFileType(file);
            //保存文件
            FileUtil.upFile(file, filePath, fileName);
            File temporary = new File(XSSEscape.escapePath(filePath + fileName));
            return ActionResult.success(MsgCode.IMP001.get());
        } else {
            return ActionResult.fail("选择文件不符合导入");
        }
    }

    @ApiOperation("导出")
    @PostMapping("/{modelId}/Actions/Export")
    public ActionResult export(@PathVariable("modelId") String modelId, @RequestBody PaginationModelExport paginationModelExport) throws ParseException, IOException, SQLException, DataException {
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);

        VisualDevJsonModel visualJsonModel = OnlinePublicUtils.getVisualJsonModel(visualdevEntity);
        //判断请求客户端来源
        String header = ServletUtil.getHeader("jnpf-origin");
        if (!"pc".equals(header)) {
            visualJsonModel.setColumnData(visualJsonModel.getAppColumnData());
        }

        String[] keys = paginationModelExport.getSelectKey();
        //关键字过滤
        List<Map<String, Object>> realList = visualdevModelDataService.exportData(keys, paginationModelExport, visualJsonModel);
        UserInfo userInfo = userProvider.get();
        DownloadVO vo = VisualUtils.createModelExcel(visualdevEntity, configValueUtil.getTemporaryFilePath(), realList, keys, userInfo);
        return ActionResult.success(vo);
    }

    @ApiOperation("功能导出")
    @PostMapping("/{modelId}/Actions/ExportData")
    public ActionResult exportData(@PathVariable("modelId") String modelId) {
        VisualdevEntity visualdevEntity = visualdevService.getInfo(modelId);
        BaseDevModelVO vo = JsonUtil.getJsonToBean(visualdevEntity, BaseDevModelVO.class);
        vo.setModelType(ExportModelTypeEnum.Design.getMessage());
        DownloadVO downloadVO = fileExport.exportFile(vo, configValueUtil.getTemporaryFilePath(), visualdevEntity.getFullName(), ModuleTypeEnum.VISUAL_DEV.getTableName());
        return ActionResult.success(downloadVO);
    }

    @ApiOperation("功能导入")
    @PostMapping(value = "/Model/Actions/ImportData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ActionResult ImportData(@RequestPart("file") MultipartFile multipartFile) throws WorkFlowException {
        //判断是否为.json结尾
        if (FileUtil.existsSuffix(multipartFile, ModuleTypeEnum.VISUAL_DEV.getTableName())) {
            return ActionResult.fail(MsgCode.IMP002.get());
        }
        //获取文件内容
        String fileContent = FileUtil.getFileContent(multipartFile);
        BaseDevModelVO vo = JsonUtil.getJsonToBean(fileContent, BaseDevModelVO.class);
        if (vo.getModelType() == null || !vo.getModelType().equals(ExportModelTypeEnum.Design.getMessage())) {
            return ActionResult.fail("请导入对应功能的json文件");
        }
        VisualdevEntity visualdevEntity = JsonUtil.getJsonToBean(vo, VisualdevEntity.class);
        String modelId = visualdevEntity.getId();
        if (StringUtil.isNotEmpty(modelId)) {
            VisualdevEntity entity = visualdevService.getInfo(modelId);
            if (entity != null) {
                return ActionResult.fail("已存在相同功能");
            }
        }
        visualdevEntity.setCreatorTime(DateUtil.getNowDate());
        visualdevEntity.setLastModifyTime(null);
        visualdevService.create(visualdevEntity);
        return ActionResult.success(MsgCode.IMP001.get());
    }

    /**
     * 模板下载
     *
     * @return
     */
    @ApiOperation("模板下载")
    @GetMapping("/TemplateDownload")
    public ActionResult<DownloadVO> templateDownload() {
        UserInfo userInfo = userProvider.get();
//        String path = configValueUtil.getTemplateFilePath() + "employee_import_template.xlsx";
        DownloadVO vo = DownloadVO.builder().build();
        try {
            vo.setName("职员信息.xlsx");
            vo.setUrl(UploaderUtil.uploaderFile("/api/file/DownloadModel?encryption=", "职员信息.xlsx" + "#" + "Temporary"));
        } catch (Exception e) {
            log.error("信息导出Excel错误:{}", e.getMessage());
        }
        return ActionResult.success(vo);
    }


}
